package fun.werfamily.wf.gateway.util;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;


/**
 * @Author: Mr.WenMing Zhang
 * @Date: 2022/07/29 17:47
 * @Description:
 **/
@Component
@Slf4j
public class TokenUtil {

    @Resource
    private RedisUtil redisUtil;

    private static final String USER_TOKEN = "auth-core:user_id:";

    private static final String TOKEN_KEY = "wf_family";
    private static final String AUTH_HEADER = "Authorization";

    private static final String TOKEN_PREFIX_REGEX = "^[B|b][E|e][A|a][R|r][E|e][R|r] .*";

    public boolean validateToken(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String authHeader = headers.getFirst(AUTH_HEADER);
        if (StringUtils.isBlank(authHeader)) {
            log.info("【JWT TOKEN】token为空,需要登录,token:{}", authHeader);
            return false;
        }
        if (!authHeader.matches(TOKEN_PREFIX_REGEX)) {
            log.info("【JWT TOKEN】token 格式错误");
            return false;
        }
        String token = extractJwtTokenFromAuthorizationHeader(authHeader);
        try {
            Claims claims = Jwts.parser().setSigningKey(TOKEN_KEY).parseClaimsJws(token).getBody();
            Long userId = Long.valueOf(claims.getId());
            String key = USER_TOKEN + userId;
            String cachedToken = redisUtil.getString(key);
            if (StringUtils.isEmpty(cachedToken)) {
                log.warn("缓存token已过期{}", token);
                return false;
            }
            cachedToken = extractJwtTokenFromAuthorizationHeader(cachedToken);
            if (!cachedToken.equals(token)) {
                log.warn("无效token={} ", token);
                return false;
            }
            log.info("id:" + claims.getId());
            log.info("subject:" + claims.getSubject());
            log.info("time:" + claims.getIssuedAt());
            log.info("userId={},userInfo={},issuedAt={}", claims.getId(), claims.getSubject(), claims.getIssuedAt());
        } catch (Exception exception) {
            log.warn("解析token异常{}", token, exception);
            return false;
        }
        return true;
    }

    private static String extractJwtTokenFromAuthorizationHeader(String auth) {
        //Replacing "Bearer Token" to "Token" directly
        return auth.replaceFirst("[B|b][E|e][A|a][R|r][E|e][R|r] ", "").replace(" ", "");
    }
}
